# encoding: utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
import re, time
import smtplib
from email.mime.text import MIMEText
from email.header import Header


class Qiangpiao(object):
    def __init__(self):
        # 邮箱配置
        self.mail_host = "smtp.qq.com"  # 设置服务器
        self.mail_user = "978326643@qq.com"  # 用户名
        self.mail_pass = "bfkmrfborcwsbcgb"  # 口令
        self.sender = '978326643@qq.com'  # 发件人
        # 搜索余票次数
        self.search_time = 0
        self.driver = webdriver.Chrome()
        # 登录的url
        self.login_url = "https://kyfw.12306.cn/otn/login/init"
        # 个人主页
        self.initMy_url = "https://kyfw.12306.cn/otn/index/initMy12306"
        # 查票
        self.search_url = "https://kyfw.12306.cn/otn/leftTicket/init"
        # 订票
        self.confirmPassenger_url = "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
        # 确定抢票车次
        self.sure_train = ''

    # 输入个人信息及车次信息
    def _inputInfo(self):
        print('请在【15分钟】内完成你的信息输入！')
        self.start = input('请输入出发地：')
        self.to_station = input('请输入目的地：')
        self.peoples = input('请输入乘车人（如有多人请用英文逗号隔开）：').split(',')
        self.start_time = input('请输入乘车日期[例如：2018-06-09]：')
        self.train_num = input('请输入抢票的车次（如有多个请用英文逗号隔开）：').split(',')
        self.my_mail = input('请输入你的邮箱，方便通知你抢票结果信息！：')
        print('请在弹出的窗口进行信息填写！')

    # 登录12306
    def _login(self):
        self._inputInfo()
        self.driver.get(self.login_url)
        WebDriverWait(self.driver, 1000).until(
            EC.url_to_be(self.initMy_url)
        )

    # 检测车票信息输入
    def _search_infor(self):
        # 1.跳转到查票页面
        self.driver.get(self.search_url)
        # 2.等待出发地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'fromStationText'), self.start)
        )
        # 3.等待目的地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'toStationText'), self.to_station)
        )
        # 4.等待出发日期是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'train_date'), self.start_time)
        )
        # 5.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 1000).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )

    # 点击查询按钮，进行车次和余票判断。
    # 用于while循环，持续检测余票信息。
    def _click_search(self):
        # 1.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )
        # 点击查询按钮
        queryBtn = self.driver.find_element_by_id('query_ticket')
        queryBtn.click()

        # 等待查询页面有数据显示
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, '//tbody[@id="queryLeftTable"]/tr'))
        )

        tr_list = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')

        for tr in tr_list:
            train_number = tr.find_element_by_class_name('number').text
            if train_number in self.train_num:
                # td[10]是硬座，td[4]是二等座
                ticket = tr.find_element_by_xpath('.//td[10]').text
                if ticket == '有' or ticket.isdigit():
                    self.sure_train = train_number
                    print('符合条件的车次有：' + train_number + '，硬座车票状态：' + ticket)
                    presentBtn = tr.find_element_by_class_name('btn72')
                    presentBtn.click()
                    # 成功检测到了符合条件的车票
                    return True
        # 未检测到符合条件的车票
        return False

    # 提交订单
    def _present(self):
        # 等待到达订单页面
        WebDriverWait(self.driver, 1000).until(
            EC.url_to_be(self.confirmPassenger_url)
        )
        print('------进入订单页面------')
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, '//ul[@id="normal_passenger_id"]/li'))
        )
        Spectator = self.driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li')
        for one in Spectator:
            person_name = one.find_element_by_xpath('./label').text
            name = re.sub(r'\(.*?\)', '', person_name)
            # print(person_name,name)
            # print('=' * 20)
            if name in self.peoples:
                personBtn = one.find_element_by_xpath('./label')
                personBtn.click()
                if self.isElementExits('//a[@id="qd_closeDefaultWarningWindowDialog_id"]'):
                    self.driver.find_element_by_xpath(
                        '//div[@id="content_defaultwarningAlert_id"]//a[@class="btn92s"]').click()

        print('乘客已选中...')

        # 选则座位等级，默认普通火车硬座
        selectTag = Select(self.driver.find_element_by_id('seatType_1'))
        # value=1是硬座，O是高铁二等座。其他的去查网站源码。
        selectTag.select_by_value('1')

        # 提交订单
        WebDriverWait(self.driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//a[@id="submitOrder_id"]'))
        )
        submitBtn = self.driver.find_element_by_xpath('//a[@id="submitOrder_id"]')
        submitBtn.click()
        # 确定订单
        WebDriverWait(self.driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//a[@id="qr_submit_id"]'))
        )
        sure_submitBtn = self.driver.find_element_by_xpath('//a[@id="qr_submit_id"]')
        WebDriverWait(self.driver, 20).until(
            EC.element_to_be_clickable((By.XPATH, '//a[@id="qr_submit_id"]'))
        )
        time.sleep(2)
        sure_submitBtn.click()
        print('订单已提交！')
        self.send_mail(to_addr=self.my_mail, content='你已成功抢到了%s车次车票，请在30分钟内前往付款！' % self.sure_train)

    # 发送邮件
    def send_mail(self, to_addr, content):
        # 三个参数：第一个为文本内容，第二个 plain 设置文本格式，第三个 utf-8 设置编码
        message = MIMEText(content, 'plain', 'utf-8')
        message['From'] = Header("抢票小程序", 'utf-8')  # 发送者
        message['Subject'] = Header('抢票结果通知', 'utf-8')
        to_addr = [to_addr]
        try:
            smtpObj = smtplib.SMTP_SSL(self.mail_host, port=465)
            smtpObj.login(self.mail_user, self.mail_pass)
            smtpObj.sendmail(self.sender, to_addr, message.as_string())
            print('通知邮件发送成功！')
        except smtplib.SMTPException as e:
            print(e)
            print('通知发送邮件失败！')

    # 检查元素是存在：
    def isElementExits(self, xpath):
        s = self.driver.find_elements_by_xpath(xpath)
        if len(s) == 0:
            return False
        else:
            return True

    # 循环查询车票
    def _put_order(self):
        while True:
            flag = self._click_search()
            if flag:
                return True
            self.search_time += 1
            print('第{}次搜索！'.format(self.search_time))
            if self.search_time > 180:
                print('已搜索180次车票信息！暂时没有符合你条件的车票！')
                return False

    def run(self):
        self._login()
        self._search_infor()
        # 如果有票，就执行订票函数。
        if self._put_order():
            self._present()


if __name__ == '__main__':
    spider = Qiangpiao()
    spider.run()
